from django.db import transaction
from rest_framework import serializers
from rest_framework.exceptions import APIException

from goods.models import SKUImage, SKU, SKUSpecification, GoodsCategory, SPU, SpecificationOption

from meiduo_mall.utils.fdfs.storage import FDFSStorage

#SKU图片序列化器类
class SKUImageSerializer(serializers.ModelSerializer):
    #关联对象嵌套序列化
    sku=serializers.StringRelatedField(label='SKU商品名称')
    sku_id=serializers.IntegerField(label='SKU商品ID')
    class Meta:
        model=SKUImage
        exclude=('create_time','update_time')

    def validate_sku_id(self,value):
        #sku商品是否存在
        try:
           SKU.objects.get(id=value)
        except SKU.DoesNotExist:
            raise serializers.ValidationError('商品不存在')

        return value

    def create(self, validated_data):
        #调用ModelSerializer中的create
        sku_image=super().create(validated_data)
        #设置SKU商品的默认图片
        sku_id=validated_data['sku_id']
        sku=SKU.objects.get(id=sku_id)

        if not sku.default_image:
            sku.default_image=sku_image.image
            sku.save()
        return sku_image


#SKU商品序列化器类
class SKUSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model=SKU
        fields=('id','name')
#商品规格信息序列化器类
class SKUSpecSerializer(serializers.ModelSerializer):
    '''商品规格信息序列化器类'''
    spec_id=serializers.IntegerField(label='规格id')
    option_id=serializers.IntegerField(label='选项id')

    class Meta:
        model=SKUSpecification
        fields=('spec_id','option_id')
#SKU商品序列化器类
class SKUSerializer(serializers.ModelSerializer):
    # 关联对象的嵌套序列化
    spu = serializers.StringRelatedField(label='SPU名称')
    spu_id = serializers.IntegerField(label='SPU ID')

    a=serializers.StringRelatedField(label='三级分类名称')
    a_id=serializers.IntegerField(label='三级分类ID',read_only=True)
    #关联对象嵌套序列化
    specs=SKUSpecSerializer(label='商品规格信息',many=True)
    class Meta:
        model = SKU
        # 排除模型的字段
        exclude = ('create_time', 'update_time', 'default_image')

    def validate(self, attrs):
        # SPU是否存在
        #获取spu_id
        spu_id=attrs['spu_id']
        #检查spu商品是否存在
        try:
            spu=SPU.objects.get(id=spu_id)
        except SPU.DoesNotExist:
            raise serializers.ValidationError('SPU商品不存在')

        # 获取第三级分类id
        attrs['category_id']= spu.category3_id#是把前端传进来的三级类别id放到attrs里面

        #校验规格数量是否正确
        spu_specs=spu.specs.all()#从数据库里面查找这一类商品规格
        specs=attrs['specs']#从前端里面传进来的

        #校验规格数量是否正确
        spu_specs_count=spu_specs.count()#查看数据库里这一类规格的个数
        specs_count=len(specs)#前端传进来的规格数据

        if spu_specs_count!=specs_count:
            raise serializers.ValidationError('规格数量有误！')
        #校验给个数据是否合法
        spu_specs_ids=[spec.id for spec in spu_specs]
        spu_specs_ids.sort()
        specs_ids=[spec.get('spec_id') for spec in specs]
        specs_ids.sort()

        if spu_specs_ids!=specs_ids:
            raise serializers.ValidationError('规格数据有误！')

        #规格选项数据是否合法
        for spec in specs:#前端传进来的数据
            #获取传递spec_id和option_id
            spec_id=spec.get('spec_id')
            option_id=spec.get('option_id')
            #获取spec_id规格的选项
            options=SpecificationOption.objects.filter(spec_id=spec_id)#从数据库里面获取的
            options_ids=[option.id for option in options]
            if option_id not in options_ids:
                raise serializers.ValidationError('选项数据有误')

        return attrs
    #保存sku商品数据
    def create(self, validated_data):
        # 保存sku商品的数据
        specs = validated_data.pop('specs')

        # 添加sku数据
        with transaction.atomic():
            # with语句块下的代码，操作数据库时，和数据库操作相关的代码都会放到同一个事务中
            sku = SKU.objects.create(**validated_data)

            for spec in specs:
                # 获取传递spec_id和option_id
                spec_id = spec.get('spec_id')
                option_id = spec.get('option_id')

                SKUSpecification.objects.create(
                    sku=sku,
                    spec_id=spec_id,
                    option_id=option_id
                )

        return sku

    def update(self, instance, validated_data):
        specs = validated_data.pop('specs')

        # 获取spec_id和option_id
        sku_specs_client = [spec for spec in specs]
        # sku_specs_client.sort()

        with transaction.atomic():
            # 修改SKU商品的数据
            sku = super().update(instance, validated_data)

            sku_specs = [{
                'spec_id': sku_spec.spec_id,
                'option_id': sku_spec.option_id
            } for sku_spec in sku.specs.all()]

            sku_specs

            if sku_specs_client != sku_specs:
                # 先删除sku规格选项数据
                sku.specs.all().delete()

                for spec in specs:
                    # 获取传递spec_id和option_id
                    spec_id = spec.get('spec_id')
                    option_id = spec.get('option_id')

                    SKUSpecification.objects.create(
                        sku=sku,
                        spec_id=spec_id,
                        option_id=option_id
                    )

        return instance


